// Demo4 Tor0id Model
// Copyright (C) 2020  Jer0en van Nugteren*/

#ifndef DF_PLASMA_HH
#define DF_PLASMA_HH

#include <armadillo> 
#include <cassert>
#include <memory>

#include "distfun.hh"

// code specific to Rat
namespace rat{namespace dm{

	// shared pointer definition
	typedef std::shared_ptr<class DFPlasma> ShDFPlasmaPr;

	// path based on the shape of a plasma in a spherical tokamak
	// thanks to Tokamak Energy for supplying the equation
	class DFPlasma: public DistFun{
		// pr0perties
		private:
			// subtract R0 from the radius such that the mesh
			// can be extruded along a circle with radius r0
			bool center_r0_ = false;

			// D-shape parameters
			rat::fltp r0_ = RAT_CONST(0.2); // [m]
			rat::fltp a_ = RAT_CONST(0.15); // [m]
			rat::fltp delta_ = RAT_CONST(0.4); // [m]
			rat::fltp kappa_ = RAT_CONST(1.9); // [m]

		// methods
		public:
			// constructor
			DFPlasma();
			DFPlasma(
				const rat::fltp a, 
				const rat::fltp r0, 
				const rat::fltp delta, 
				const rat::fltp kappa, 
				const bool center_r0 = false);

			// factory methods
			static ShDFPlasmaPr create();
			static ShDFPlasmaPr create(
				const rat::fltp a, 
				const rat::fltp r0, 
				const rat::fltp delta, 
				const rat::fltp kappa, 
				const bool center_r0 = false);

			// set plasma parameters
			void set_r0(const fltp r0);
			void set_center_r0(const bool center_r0 = true);
			void set_a(const fltp a);
			void set_delta(const fltp delta);
			void set_kappa(const fltp kappa);

			// get plasma parameters
			fltp get_r0() const;
			bool get_center_r0() const;
			fltp get_a() const;
			fltp get_delta() const;
			fltp get_kappa() const;

			// perimeter function
			virtual ShPerimeterPr create_perimeter(const fltp delem) const override;

			// get bounding box
			virtual arma::Mat<fltp>::fixed<2,2> get_bounding() const override;

			// distance function
			virtual arma::Col<fltp> calc_distance(const arma::Mat<fltp> &p) const override;

			// vallidity check
			bool is_valid(const bool enable_throws) const override;

			// serialization
			static std::string get_type();
			virtual void serialize(
				Json::Value &js, 
				rat::cmn::SList &list) const override;
			virtual void deserialize(
				const Json::Value &js, 
				rat::cmn::DSList &list, 
				const rat::cmn::NodeFactoryMap &factory_list, 
				const boost::filesystem::path &pth) override;
	};

}}

#endif